package boboUtil;

public abstract class BoboAbstractList<E> extends BoboAbstractCollection<E> implements BoboList<E> {
    protected transient int modCount = 0;

    public boolean add(E e) {
        add(size(), e);
        return true;
    }

    public int indexOf(Object o) {
        BoboListIterator<E> it = listIterator();
        if (o == null) {
            while (it.hasNext()) {
                if (it.next() == null)
                    return it.previousIndex();
            }
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return it.previousIndex();
        }
        return -1;
    }

    public int lastIndexOf(Object o) {
        BoboListIterator<E> it = listIterator(size());
        if (o == null) {
            while (it.hasPrevious())
                if (it.previous() == null)
                    return it.nextIndex();
        } else {
            while (it.hasPrevious())
                if (o.equals(it.previous()))
                    return it.nextIndex();
        }
        return -1;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        BoboListIterator<E> it = listIterator(fromIndex);
        for (int i = 0, n = toIndex - fromIndex; i < n; i++) {
            it.next();
            it.remove();
        }
    }

    @Override
    public void clear() {
        removeRange(0, size());
    }

    public BoboIterator<E> iterator(){
        return new Itr();
    }

    public BoboListIterator<E> listIterator(final int index){
        return new ListItr(index);
    }

    public BoboListIterator<E> listIterator(){
        return listIterator(0);
    }

    @Override
    public int hashCode() {
        int hashCode = 1;
        BoboIterator it = iterator();
        while (it.hasNext()){
            hashCode = hashCode*31 + (it.next() == null? 0 : it.next().hashCode());
        }
        return hashCode;
    }

    //普通迭代器，除了遍历，还可以 remove
    private class Itr implements BoboIterator<E> {

        int cursor = 0;
        int lastRet = -1;
        int expectModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();

            int i = cursor;
            E next = get(i);
            lastRet = i;
            cursor = i + 1;
            return next;
        }

        public void remove() {
            if (lastRet < 0){
                System.out.println("exception: lastRet < 0");
                return;
            }
            checkForComodification();
            /*
            * 当成员内部类拥有和外部类同名的成员变量或者方法时，
            * 会发生隐藏现象，即默认情况下访问的是成员内部类的成员。
            * 如果要访问外部类的同名成员，需要以下面的形式进行访问：
            * 外部类.this.成员变量
            * 外部类.this.成员方法
            * */
            BoboAbstractList.this.remove(lastRet);
            if (lastRet < cursor)   cursor--;
            lastRet = -1;
            expectModCount = modCount;

        }

        final void checkForComodification() {
            if (expectModCount != modCount) {
                System.out.println("exception: expectModCount != modCount");
            }
        }
    }

    //List迭代器，可前后遍历，并且进增加修改操作：add set
    private class ListItr extends Itr implements BoboListIterator<E>{

        ListItr(int index){
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() {
            checkForComodification();
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;

            return previous;
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0){
                System.out.println("exception: lastRet < 0");
                return;
            }
            checkForComodification();
            BoboAbstractList.this.set(lastRet, e);
            expectModCount = modCount;
        }

        public void add(E e) {
            checkForComodification();

            int i = cursor;
            BoboAbstractList.this.add(i, e);
            cursor = i+1;
            lastRet = -1;
            expectModCount = modCount;
        }
    }
}
